package iscript.coreFramework.math 
{
	import flash.display.Graphics;

	public class Vector2D 
	{
		
		private var  _P0:Point2D;		
		private var  _P1:Point2D;
		
		/***
		 **CODE:
			 * 
			 * new Vector2D(x:Number,y:Number)
			 * new Vector2D(p:Point2D)
			 * new Vector2D(p0:Point2D,p1:Point2D)
			 * 
		 **/
		
		public function Vector2D (P0:Point2D,P1:Point2D):void {		
                 _P0 = P0;
				 _P1 = P1;
	     }
     
	    public function clone():Vector2D {
            return new Vector2D(_P0,_P1);
         }
	    /**
          * 绘制一条线段
          * @param	graphics
          * @param	color
          */
        public  function draw(graphics:Graphics, color:uint = 0):void {
            graphics.lineStyle (0, color);
            graphics.moveTo (_P0.x, _P0.y);
            graphics.lineTo (_P1.x, _P1.y);
        }
	 
	    public  function  set  P0(value:Point2D):void {
			  _P0 = value;
			}
		public  function  get  P0():Point2D {
			  return  _P0;
			}
			
		public  function  set  P1(value:Point2D):void {
			  _P1 = value;
			}
			
		public  function  get  P1():Point2D {
			  return  _P1;
			}	
		 
		
		/**
		 * x分量 运动量
		 */
		public function get vx():Number { return P1.x - P0.x; }
		
		public function set vx(value:Number):void {
			    _P1.x =  _P0.x + value
			};
		/**
		 * y分量 运动量
		 */
		public function get vy():Number { return P1.y-P0.y; }	
		public function set vy(value:Number):void { 
			  _P1.y = _P0.y + value;
			}	
		/**
		 * 向量的归一化 长度为1的向量，称为归一化向量
		 */
		public function get dx():Number { return vx / length; }
		public function get dy():Number { return vy / length; }
		
		
		public function  get  length():Number {			
			 return Math.sqrt(vx*vx+vy*vy);
			}
		
		public function get angle():Number {
			return Math.atan2(vy,vx)
			}
		 
		public function set angle(value:Number):void {
            vx = Math.cos(value) * length;
            vy = Math.sin(value) * length;
			}	
			
		/**
		 * 右法线 X
		 */
		public function get rx():Number {
			return  -vy;
			}
		/**
		 * 右法线 Y
		 */	
		public function get ry():Number {
			return  vx;
			}
		
		/**
		 * 左法线 X
		 */	
		public function get lx():Number {
			return  vy;
			}
		
		/**
		 * 左法线 Y
		 */		
		public function get ly():Number {
			return  -vx;
			}			
			
			
		public function  leftNormalLine():Number {
			return 0;
			}
		
			
		public function  rightNormalLine():Number {
			return 0;
			}	
		
			
		 /**
         * 判断当前向量是否是单位向量,长度为1的向量就是单位向量.
         * @return
         */
        public function isNormalized():Boolean {
            return length == 1;
        	}	
			
        /**
         * 判断当前向量是否是零向量,长度为0的向量就是零向量.
         * @return
         */
        public function isZero():Boolean {
            return length == 0;
        	}	
         
        /**
         * 返回两向量夹角的弦度值
         * @param	v1
         * @param	v2
         * @return
         */
		static public function angleBetween (v1:Vector2D, v2:Vector2D):Number {
	            if (!v1.isNormalized()) {
	                v1=v1.clone().normalize();
	            }
	            if (!v2.isNormalized()) {
	                v2=v2.clone().normalize();
	            }
	            return Math.acos(v1.dotProd(v2));
	           //return Math.acos(v1.dotProd(v2)/(v1.length*v2.length));
	        }
        
	    /**
	     * 返回两个向量真实的夹角(带负角度)弧度值 
	     * @param	v1
	     * @param	v2
	     * @return
	     */
		static public function rawAngleBetween (v1:Vector2D, v2:Vector2D):Number {
			    return  v2.angle-v1.angle;
	         }
	          
	     /**
	      * V2是否在V1的逆时针方向.
	      * @param	v1
	      * @param	v2
	      * @return
	      */
	    static public  function  isReverse(v1:Vector2D, v2:Vector2D):Boolean {
			   var angle:Number = MathUtil.getRawAngle(Vector2D.rawAngleBetween(v1, v2))
		       return angle > 180 && angle<=360;
		   }
	
		/**
		 * V2是否在V1的顺时针方向.
		 * @param	v1
		 * @param	v2
		 * @return
		 */   
		 static public  function  isOrder(v1:Vector2D, v2:Vector2D):Boolean {
			   var angle:Number = MathUtil.getRawAngle(Vector2D.rawAngleBetween(v1, v2))
		       return  angle<= 180 && angle>0 ;	   
		   }   
		   
		/**
		 * 向量点乘(向量积)
		 * 如果是正数，那么2个向量的方向是相同的(夹角小于90度)，如果是负数，那么2个向量的方向是相反的(夹角大于90度)。
		 * @param	v2
		 * @return
		 */
		public function dotProd (v2:Vector2D):Number {
            return  this.vx * v2.vx + this.vy* v2.vy;
        }	
	    
        /**
         * 2个向量是否交叉
         * @param	v2
         * @return
         */
		public function isCross(v2:Vector2D):Boolean {
			//(v1.dx==v2.dx and v1.dy==v2.dy) or
			//(v1.dx==-v2.dx and v1.dy==-v2.dy)
			if (this.dx == v2.dx && this.dy == v2.dy) return false;
			if (this.dx == -v2.dx && this.dy == -v2.dy) return false;				
			return true;
			}
         
			
			
		/**
		 * 获得交叉坐标
		 * @param	v2
		 * @return
		 */
		public function crossPoint(v2:Vector2D):Point2D {
				var v3:Vector2D = new Vector2D(this._P0,v2._P0);
				var t:Number = crossPerp(v3, v2) / crossPerp(this, v2);
				var p:Point2D = new Point2D();
					p.x = this._P0.x + this.vx * t;
					p.y = this.P0.y + this.vy * t;
				return  p;
			}	
		
		/**
		 * 两个向量是否垂直相交 [1:垂直相交]
		 * @param	va
		 * @param	vb
		 * @return
		 */
		public function crossPerp(va:Vector2D, vb:Vector2D):Number{
			return  va.vx*vb.vy - va.vy*vb.vx;
		}
			
		//向量的投影也是一个向量。我们先计算出2个向量的点乘，再乘以向量v2的归一化向量，就得到了投影
         /**
          * 向量的投影 X
          * @param	v2
          * @return
          */
         public function projectionX(v2:Vector2D):Number {
			return  dotProd(v2) * v2.dx;
			}
         
		 	
		 /**
          * 向量的投影 Y
          * @param	v2
          * @return
          */	
		 public function projectionY(v2:Vector2D):Number {
			return  dotProd(v2) * v2.dy;
			}


		/**
		 * 向量的归一化
		 * @return
		 */
		public function normalize():Vector2D {
            if (length == 0) {
                this.vx = 1;
                return this;
            }
            var len:Number = length;
            vx /= len;
            vy /=len;
            return this;
         }

         /**
         * 返回坐标向量
         */
        public function get perp ():Vector2D {
            return new Vector2D(_P1,_P0);
        }

        
        public function toString():String {
			 return  "Vector2D[(" + _P0.toString() + "),(" + _P1.toString() + ")]";
			}
          
		static	public function  create(data:String):Vector2D {
			 var arr:Array = data.split(",");
			 return  new Vector2D(arr[0], arr[1]);
			}
	}

}